package org.example.test;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

/**
 * 题目
 * 1、有一家超市，出售苹果和草莓。其中苹果 8 元/斤，草莓 13 元/斤。
 * 现在顾客 A 在超市购买了若干斤苹果和草莓，需要计算一共多少钱？
 * 请编写函数，对于 A 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 * <p>
 * 2、超市增加了一种水果芒果，其定价为 20 元/斤。
 * 现在顾客 B 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 B 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 * <p>
 * 3、超市做促销活动，草莓限时打 8 折。
 * 现在顾客 C 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 C 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 * <p>
 * 4、促销活动效果明显，超市继续加大促销力度，购物满 100 减 10 块。
 * 现在顾客 D 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 D 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 * <p>
 * 要求
 * 使用 Java 程序编写，IDE 不限，
 * 请使用面向对象的思路进行程序编写。
 * 需在程序中，验证函数计算结果的正确性。
 * <p>
 * 提示
 * 顾客购买的水果斤数，可自行确定。无论数值为多少，均需验证程序计算结果的正确性。
 * 可以编写多个函数分别实现，也可以只编写一个函数实现，方式不限。
 * 面试时，请准备电脑及 IDE 环境进行现场演示。
 * 若能将代码提交到 github、gitee、gitlab 等代码托管仓库，提供代码仓库地址更佳。
 *
 * @author 玉启锐  Yuqirui  Email: 1464025388@qq.com
 * creationTime 2024-03-02 16:20:25
 * @since v1.0.0
 */
public class Main {


    /**
     * main方法
     *
     * @param args 参数
     * @author 启锐  Yuqirui  Email: 1464025388@qq.com
     * creationTime 2024-03-02 16:20:40
     * @since v1.4.0
     */
    public static void main(String[] args) {
        // 问题1
        List<Fruit> fruitList = new ArrayList<>();
        Fruit fruit = new Fruit();
        fruit.setFruitCode("PG");
        fruit.setFruitName("苹果");
        fruit.setFruitPrice(new BigDecimal("8.00"));
        fruit.setFruitWeight(10);
        fruit.setDiscount(new BigDecimal("1"));
        fruitList.add(fruit);

        fruit = new Fruit();
        fruit.setFruitCode("CM");
        fruit.setFruitName("草莓");
        fruit.setFruitPrice(new BigDecimal("13.00"));
        fruit.setFruitWeight(10);
        fruit.setDiscount(new BigDecimal("1"));
        fruitList.add(fruit);
        // (10 * 8 * 1) + (10 * 13 * 1) = 80 + 130 = 210
        System.out.println("问题1 总价钱" + computeAllPrice(fruitList, null)); // 210.00


        // 问题2
        fruit = new Fruit();
        fruit.setFruitCode("MG");
        fruit.setFruitName("芒果");
        fruit.setFruitPrice(new BigDecimal("20.00"));
        fruit.setFruitWeight(10);
        fruit.setDiscount(new BigDecimal("1"));
        fruitList.add(fruit);
        // (10 * 8 * 1) + (10 * 13 * 1) + (10 * 20 * 1) = 80 + 130 + 200 = 410
        System.out.println("问题2 总价钱" + computeAllPrice(fruitList, null)); // 410


        // 问题3
        for (Fruit fruit1 : fruitList) {
            if (fruit1.getFruitCode().equals("CM")) {
                fruit1.setDiscount(new BigDecimal("0.8"));
                break;
            }
        }
        // (10 * 8 * 1) + (10 * 13 * 0.8) + (10 * 20 * 1) = 80 + 130 + 200 = 384
        System.out.println("问题3 总价钱" + computeAllPrice(fruitList, null)); // 384


        //  ====== ===  问题4
        // 在问题3的基础上 - 40 ： 384 - 40 = 344
        System.out.println("问题4-1 总价钱" + computeAllPrice(fruitList, Boolean.FALSE)); // 344
        // 在问题3的基础上 - 10 ： 384 - 10 = 374
        System.out.println("问题4-2 总价钱" + computeAllPrice(fruitList, Boolean.TRUE)); // 374


    }


    /**
     * 计算所有价格
     *
     * @param fruitList 客户购买的水果集合
     * @param flag      true: 总的满 100-10，例如 totalPrice = 500, 应支付 490元
     *                  false: 只要满100就减10元，满400 - 40，例如totalPrice = 458,应支付 458 - 40 =  418
     * @return {@link BigDecimal }
     * @author 启锐  Yuqirui  Email: 1464025388@qq.com
     * creationTime 2024-03-02 16:21:06
     * @since v1.4.0
     */
    public static BigDecimal computeAllPrice(List<Fruit> fruitList, Boolean flag) {
        BigDecimal totalPrice = new BigDecimal("00.00");

        // 判断集合是否为空，空直接返回总价 0 即可
        if (fruitList.size() < 1) {
            return totalPrice;
        }
        for (Fruit fruit : fruitList) {
            // 数据校验
            if (fruit.getFruitWeight() < 0) {
                throw new RuntimeException("购买的" + fruit.getFruitName() + "斤数必须大于或等于0");
            }
            if (fruit.getFruitPrice().compareTo(new BigDecimal("0.00")) < 0) {
                throw new RuntimeException("购买的" + fruit.getFruitName() + "单价必须大于或等于0");
            }

            if (null == fruit.getDiscount()) {
                throw new RuntimeException("折扣不能为空");
            } else {
                if (fruit.getDiscount().compareTo(new BigDecimal("0.00")) <= 0 ||
                        fruit.getDiscount().compareTo(new BigDecimal("1.00")) > 0) {
                    throw new RuntimeException("购买的" + fruit.getFruitName() + "折扣区间须在 0 ～ 1");
                }
            }

            // 单价 * 重量 * 折扣
            totalPrice = totalPrice.add(fruit.getFruitPrice()
                    .multiply(new BigDecimal(fruit.getFruitWeight()))
                    .multiply(fruit.getDiscount()));
        }
        if (null != flag) {
            // true: 总的满 100-10
            if (flag) {
                totalPrice = totalPrice.subtract(new BigDecimal("10.00"));
            } else {
                // false: 只要满100就减10元，满400 - 40
                BigDecimal fullMinus = new BigDecimal("100");
                totalPrice = totalPrice.subtract(totalPrice.divide(fullMinus, 0, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("10")));
            }
        }
        return totalPrice;
    }

    public static class Fruit {

        /**
         * 水果代码
         */
        private String fruitCode;

        /**
         * 水果名称
         */
        private String fruitName;


        /**
         * 水果价格
         */
        private BigDecimal fruitPrice;

        /**
         * 果实重量
         */
        private Integer fruitWeight;

        /**
         * 水果折扣
         */
        private BigDecimal discount;

        public String getFruitName() {
            return fruitName;
        }

        public void setFruitName(String fruitName) {
            this.fruitName = fruitName;
        }

        public BigDecimal getFruitPrice() {
            return fruitPrice;
        }

        public void setFruitPrice(BigDecimal fruitPrice) {
            this.fruitPrice = fruitPrice;
        }

        public Integer getFruitWeight() {
            return fruitWeight;
        }


        public void setFruitWeight(Integer fruitWeight) {
            this.fruitWeight = fruitWeight;
        }

        public BigDecimal getDiscount() {
            return discount;
        }

        public void setDiscount(BigDecimal discount) {
            this.discount = discount;
        }

        public String getFruitCode() {
            return fruitCode;
        }

        public void setFruitCode(String fruitCode) {
            this.fruitCode = fruitCode;
        }

        @Override
        public String toString() {
            return "Fruit{" +
                    "fruitCode='" + fruitCode + '\'' +
                    ", fruitName='" + fruitName + '\'' +
                    ", fruitPrice=" + fruitPrice +
                    ", fruitWeight=" + fruitWeight +
                    ", discount=" + discount +
                    '}';
        }
    }

}
